
import { bindThis } from '../tools/utils.js';


/**
 * 数据筛选器
 * 
 * @param {Array} data 数据源
 * @param {Object} options 配置项
 * @param {String|Array|Function} options.filter 过滤字段，支持字符串、数组、函数；如果是函数时必须返回字符串数组
 * @param {Function} options.onFilter 过滤完成回调
 * @param {Number} options.shake 防抖时间，为0或false不开启防抖
 * @param {String} options.mode 匹配模式，默认normal，如下：
 * normal:常规模式，匹配输入内容，必须包含全部字符，要求按输入顺序，不要求连续
 * strict:严格匹配，匹配输入内容，必须包含全部字符，要求按输入顺序，要求连续
 * loose:宽松匹配，匹配输入内容，只需包含任意字符，要求按输入顺序，不要求连续
 * 
 */
export default class SelectFilter {

  static classType = 'SelectFilter';
  get classType() {
    return SelectFilter.classType;
  }

  _data = null;
  // 预计算数据：创建所有条目的指标缓存（只需要在数据变化时更新）
  entryCache = null;
  // 预缓存数据结构（只需初始化一次）
  charPositionMap = null;
  _options = {
    key: 'id', // 数据唯一标识
    shake: 300, // 防抖时间，为0或false不开启防抖
    mode: 'normal', // 匹配模式，normal:常规模式，strict:严格匹配，loose:宽松匹配
    filter: 'name', // 过滤字段，支持字符串、数组、函数
    onFilter(){} // 过滤完成回调
  };

  constructor(data, options) {
    this._data = data;
    Object.assign(this._options, options);
    if (options.onFilter instanceof Function) {
      options.onFilter(data);
    }

    // 设置搜索字段
    this._initFilterField();

    return bindThis(this);
  }

  _initFilterField() {
    let self = this;
    let opt = self._options;
    let mapper = {};
    if (opt.filter instanceof Function) {
      self._data.forEach(item => {
        mapper[item[opt.key]] = opt.filter(item);
      });
    } else if (typeof (opt.filter) == 'string') {
      // 取其字段
      self._data.forEach(item => {
        mapper[item[opt.key]] = [item[opt.filter]];
      });
    } else if (opt.filter instanceof Array) {
      self._data.forEach(item => {
        let arr = [];
        opt.filter.forEach(it => {
          arr.push(item[it]);
        });
        mapper[item[opt.key]] = arr;
      });
    } else {
      throw new Error('filter must be function or string or array');
    }

    // self.initCache(mapper);
    self.mapper = mapper;
  }


  filterMethod(input) {
    let self = this;
    self.input = input;
    if (self.timer) {
      clearTimeout(self.timer);
      self.timer = null;
    }
    if (!input) {
      self._options.onFilter(self._data);
      return;
    }

    if (self._options.shake) {
      // 使用防抖方式
      self.timer = setTimeout(() => {
        self.filter();
      }, self._options.shake);
    } else {
      // 直接搜索
      self.filter();

    }

  }

  filter() {
    let self = this;
    let result = filterAndSort(self.mapper, self.input, self._options.mode);
    if (!result.length) {
      self._options.onFilter([]);
      return;
    }
    let res = [];
    result.forEach(it=>{
      let value = self._data.find(item => item[self._options.key] == it);
      if (value){
        res.push(value);
      }
    });
    self._options.onFilter(res);
  }
}




function filterAndSort(filterMapper, input, strictMode) {
  // 处理输入为空的情况：返回所有key
  if (input === '') {
    return Object.keys(filterMapper);
  }

  const inputLength = input.length;
  const results = [];

  // 遍历所有键值对
  Object.entries(filterMapper).forEach(([key, stringArray]) => {
    let bestMatch = null;

    // 遍历该键的所有字符串
    for (const str of stringArray) {
      let matchResult = null;

      // 根据模式选择匹配策略
      switch (strictMode) {
      case 'strict': // 严格模式：连续完整匹配
        const index = str.indexOf(input);
        if (index !== -1) {
          matchResult = {
            count: inputLength,
            maxContinuous: inputLength,
            firstIndex: index
          };
        }
        break;

      case 'normal': // 普通模式：全字符按顺序匹配（不要求连续）
        matchResult = sequentialMatch(str, input, false);
        break;

      case 'loose': // 宽松模式：任一字符匹配
        matchResult = anyCharacterMatch(str, input);
        break;
      }

      // 如果找到匹配，更新最佳匹配结果
      if (matchResult &&
        (!bestMatch || isBetterMatch(matchResult, bestMatch))) {
        bestMatch = matchResult;
      }
    }

    // 记录最佳匹配的key
    if (bestMatch !== null) {
      results.push({
        key,
        matchMetrics: bestMatch
      });
    }
  });

  // 高性能排序并返回key
  return results.sort((a, b) => {
    const ma = a.matchMetrics;
    const mb = b.matchMetrics;

    // 1. 匹配字符数优先（降序）
    if (mb.count !== ma.count) return mb.count - ma.count;

    // 2. 最长连续长度（降序）
    if (mb.maxContinuous !== ma.maxContinuous) return mb.maxContinuous - ma.maxContinuous;

    // 3. 首个匹配位置（升序）
    return ma.firstIndex - mb.firstIndex;
  }).map(item => item.key);

  // === 匹配算法辅助函数 ===

  // 顺序匹配算法（用于普通模式）
  function sequentialMatch(str, pattern) {
    let count = 0;
    let currentStreak = 0;
    let maxContinuous = 0;
    let firstIndex = -1;
    let searchStart = 0;
    let prevPos = -1;

    for (let i = 0; i < pattern.length; i++) {
      const char = pattern[i];
      const pos = str.indexOf(char, searchStart);

      // 字符未找到
      if (pos === -1) {
        // 普通模式要求所有字符必须匹配
        if (strictMode === 'normal') return null;
        continue;
      }

      // 更新匹配指标
      count++;
      searchStart = pos + 1;

      // 记录首个匹配位置
      if (firstIndex === -1) firstIndex = pos;

      // 连续性计算
      if (i > 0 && pos === prevPos + 1) {
        currentStreak++;
        maxContinuous = Math.max(maxContinuous, currentStreak);
      } else {
        currentStreak = 1;
        maxContinuous = Math.max(maxContinuous, 1);
      }

      prevPos = pos;
    }

    // 普通模式要求匹配所有字符
    if (strictMode === 'normal' && count !== pattern.length) {
      return null;
    }

    // 最终连续性检查
    maxContinuous = Math.max(maxContinuous, currentStreak);

    return count > 0 ? { count, maxContinuous, firstIndex } : null;
  }

  // 宽松模式匹配算法
  function anyCharacterMatch(str, pattern) {
    let count = 0;
    let firstIndex = Infinity;
    let currentStreak = 0;
    let maxContinuous = 0;
    let prevPos = -1;

    // 查找任意匹配字符
    for (let i = 0; i < pattern.length; i++) {
      const char = pattern[i];
      const pos = str.indexOf(char);

      if (pos === -1) continue;

      count++;

      // 更新首个匹配位置
      if (pos < firstIndex) firstIndex = pos;

      // 连续性计算（宽松模式下按出现顺序）
      if (prevPos !== -1 && pos > prevPos) {
        currentStreak++;
        maxContinuous = Math.max(maxContinuous, currentStreak);
      } else {
        currentStreak = 1;
        maxContinuous = Math.max(maxContinuous, 1);
      }

      prevPos = pos;
    }

    // 至少需要匹配一个字符
    return count > 0 ? { count, maxContinuous, firstIndex } : null;
  }

  // 辅助函数：判断新匹配是否更好
  function isBetterMatch(newMatch, bestMatch) {
    // 1. 比较匹配字符数
    if (newMatch.count > bestMatch.count) return true;
    if (newMatch.count < bestMatch.count) return false;

    // 2. 比较最长连续
    if (newMatch.maxContinuous > bestMatch.maxContinuous) return true;
    if (newMatch.maxContinuous < bestMatch.maxContinuous) return false;

    // 3. 比较首次出现位置
    return newMatch.firstIndex < bestMatch.firstIndex;
  }
}








